home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / DesktopDoubler / NubApp / Notice.c < prev    next >
Text File  |  1999-06-23  |  8KB  |  353 lines

  1. #define DISABLE_LOCAL_CALLTRACE        1        // Set to 1 to disable Call Traces for this file.
  2. #define DISABLE_LOCAL_DEBUG            0        // Set to 1 to disable all debugging for this file.
  3. #include "DebugUtils.h"
  4.  
  5. #include <ctype.h>
  6. #include <Icons.h>
  7. #include <Fonts.h>
  8. #include <Gestalt.h>
  9. #include <Notification.h>
  10. #include <Resources.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include "Main.h"
  14. #include "Notice.h"
  15. #include "QDUtils.h"
  16. #include "StringUtils.h"
  17.  
  18.  
  19.  
  20.  
  21.  
  22. void PreflightNotice(Boolean blockEvents)
  23. {
  24.     char        name[32];
  25.     EventRecord    event;
  26.     Str255        msg;
  27.     NMRec        nmpb;
  28.     OSStatus    err;
  29.     
  30.     
  31.     // Are we the front process?
  32.     if (WeAreFrontProcess())
  33.         return;
  34.     
  35.     // Post a notification, and wait until
  36.     // our process is switched to the front.
  37.     GetAppNameCString(name);
  38.     msg[0] = sprintf((char*)&msg[1],"%s requires your attention.  Please bring %s to the front.",name,name);
  39.     
  40.     memset(&nmpb,0,sizeof(nmpb));
  41.     nmpb.qType = nmType;
  42.     nmpb.nmMark = 1;
  43.     
  44.     err = GetIconSuite(&nmpb.nmIcon,128,svAllSmallData);
  45.     if (err != noErr)
  46.         nmpb.nmIcon = NULL;
  47.     
  48.     nmpb.nmSound = (Handle)-1;
  49.     nmpb.nmStr = msg;
  50.     NMInstall(&nmpb);
  51.     
  52.     if (blockEvents)
  53.     {
  54.         while(!WeAreFrontProcess())
  55.         {
  56.             EventRecord    event;
  57.             WaitNextEvent(0,&event,60L,NULL);
  58.         }
  59.     }
  60.     else
  61.     {
  62.         while(!WeAreFrontProcess())
  63.             SubEventLoop(everyEvent,1L);
  64.     }
  65.     
  66.     NMRemove(&nmpb);
  67.     if (nmpb.nmIcon) DisposeIconSuite(nmpb.nmIcon,true);
  68.     if (nmpb.nmResp) DisposeRoutineDescriptor(nmpb.nmResp);
  69. }
  70.  
  71.  
  72.  
  73.  
  74.  
  75. void PostNotice(AlertType type,const StringPtr error,const StringPtr detail)
  76. {
  77.     AlertStdAlertParamRec        param;
  78.     short                        item;
  79.     
  80.     
  81.     // Ensure we are front process.
  82.     PreflightNotice(false);
  83.     
  84.     // Do it our way..call CompatibleStandardAlert and we'll be done.
  85.     param.movable = false;
  86.     param.helpButton = false;
  87.     param.filterProc = NULL;
  88.     param.defaultText = (StringPtr)-1L;                // default = "OK"
  89.     param.cancelText = NULL;                        // no cancel button
  90.     param.otherText = NULL;                            // no other button
  91.     param.defaultButton = kAlertStdAlertOKButton;
  92.     param.cancelButton = 0;
  93.     param.position = 0;                                // Alert position on main screen
  94.         
  95.     CompatibleStandardAlert(type,error,detail,¶m,&item);
  96. }
  97.  
  98.  
  99.  
  100.  
  101.  
  102. Boolean PostQuestion(AlertType type,const StringPtr error,const StringPtr detail)
  103. {
  104.     AlertStdAlertParamRec        param;
  105.     short                        item;
  106.     
  107.     
  108.     // Ensure we are front process.
  109.     PreflightNotice(false);
  110.     
  111.     // Do it our way..call CompatibleStandardAlert and we'll be done.
  112.     param.movable = false;
  113.     param.helpButton = false;
  114.     param.filterProc = NULL;
  115.     param.defaultText = (StringPtr)-1L;                // default = "OK"
  116.     param.cancelText = (StringPtr)-1L;                // default = "Cancel'
  117.     param.otherText = NULL;                            // no other button
  118.     param.defaultButton = kAlertStdAlertOKButton;
  119.     param.cancelButton = kAlertStdAlertCancelButton;
  120.     param.position = 0;                                // Alert position on main screen
  121.     
  122.     CompatibleStandardAlert(type,error,detail,¶m,&item);
  123.     
  124.     return (item == 1);
  125. }
  126.  
  127.  
  128.  
  129.  
  130.  
  131. #define kCSATextBoxTop                9
  132. #define kCSATextBoxLeft                76
  133. #define kCSATextBoxWidth            (368 - kCSATextBoxLeft - 10)
  134. #define kCSATextBoxSeparator        5
  135. #define kCSATextBoxCompensation        10
  136.  
  137. typedef struct CSAInfo
  138. {
  139.     StringPtr    errorText;
  140.     StringPtr    detailText;
  141.     AlertType    alertType;
  142. } CSAInfo;
  143.  
  144. OSErr CompatibleStandardAlert(AlertType inAlertType,StringPtr inError,StringPtr inExplanation,
  145.                             AlertStdAlertParamPtr inAlertParam,SInt16 *outItemHit)
  146. {
  147.     DialogPtr    dialog;
  148.     SInt32        result;
  149.     OSStatus    err;
  150.     
  151.     
  152.     err = Gestalt('appr',&result);
  153.     if ((err == noErr) && (result & 1))
  154.         return StandardAlert(inAlertType,inError,inExplanation,inAlertParam,outItemHit);
  155.     
  156.     dialog = GetNewDialog(1000,NULL,(WindowPtr)(-1L));
  157.     if (dialog)
  158.     {
  159.         QDContext    context(dialog);
  160.         UserItemUPP    userItemUPP;
  161.         SInt16        iType,errHeight,detailHeight,height;
  162.         Point        loc;
  163.         Handle        iHandle;
  164.         Rect        iRect;
  165.         UInt32        size;
  166.         CSAInfo        info;
  167.         
  168.         
  169.         info.errorText = inError;
  170.         info.detailText = inExplanation;
  171.         info.alertType = inAlertType;
  172.         SetWRefCon(dialog,(long)&info);
  173.         
  174.         userItemUPP = NewUserItemProc(CompatibleStandardAlertUserItem);
  175.         errHeight = DrawAutoSizedText(inError,systemFont,12,0,0,kCSATextBoxWidth,false);
  176.         detailHeight = DrawAutoSizedText(inExplanation,applFont,10,0,0,kCSATextBoxWidth,false);
  177.         
  178.         height = errHeight + detailHeight + ((errHeight && detailHeight) ? (kCSATextBoxSeparator - kCSATextBoxCompensation) : 0);
  179.         SizeWindow(dialog,dialog->portRect.right,dialog->portRect.bottom + height,false);
  180.         
  181.         GetDialogItem(dialog,1,&iType,&iHandle,&iRect);
  182.         OffsetRect(&iRect,0,height);
  183.         SetDialogItem(dialog,1,iType,iHandle,&iRect);
  184.         MoveControl((ControlHandle)iHandle,iRect.left,iRect.top);
  185.         GetDialogItem(dialog,2,&iType,&iHandle,&iRect);
  186.         OffsetRect(&iRect,0,height);
  187.         SetDialogItem(dialog,2,iType,iHandle,&iRect);
  188.         MoveControl((ControlHandle)iHandle,iRect.left,iRect.top);
  189.         GetDialogItem(dialog,3,&iType,&iHandle,&iRect);
  190.         iRect.bottom += height + kCSATextBoxCompensation;
  191.         SetDialogItem(dialog,3,iType,(Handle)userItemUPP,&iRect);
  192.         
  193.         if (inAlertParam->defaultButton)
  194.             SetDialogDefaultItem(dialog,inAlertParam->defaultButton);
  195.         if (!inAlertParam->defaultText)
  196.         {
  197.             GetDialogItem(dialog,1,&iType,&iHandle,&iRect);
  198.             HideControl((ControlHandle)iHandle);
  199.         }
  200.         
  201.         if (inAlertParam->cancelButton)
  202.             SetDialogCancelItem(dialog,inAlertParam->cancelButton);
  203.         if (!inAlertParam->cancelText)
  204.         {
  205.             GetDialogItem(dialog,2,&iType,&iHandle,&iRect);
  206.             HideControl((ControlHandle)iHandle);
  207.         }
  208.         
  209.         ShowWindow(dialog);
  210.         ModalDialog(NULL,outItemHit);
  211.         
  212.         DisposeRoutineDescriptor(userItemUPP);
  213.         DisposeDialog(dialog);
  214.     }
  215.     
  216.     return 0;
  217. }
  218.  
  219.  
  220.  
  221.  
  222.  
  223. pascal void CompatibleStandardAlertUserItem(WindowPtr window,short item)
  224. {
  225.     QDContext    context(window);
  226.     CSAInfo        *info = (CSAInfo*)GetWRefCon(window);
  227.     short        offset,iconID;
  228.     
  229.     
  230.     switch(info->alertType)
  231.     {
  232.         case kAlertStopAlert:
  233.             iconID = 0;
  234.             break;
  235.         
  236.         case kAlertNoteAlert:
  237.             iconID = 1;
  238.             break;
  239.         
  240.         case kAlertCautionAlert:
  241.             iconID = 2;
  242.             break;
  243.             
  244.         default:
  245.             iconID = -1;
  246.             break;
  247.     }
  248.     
  249.     if (iconID != -1)
  250.     {
  251.         CIconHandle    cicon;
  252.         Rect        box;
  253.         
  254.         
  255.         box.left = 20;
  256.         box.top = 9;
  257.         box.right = box.left + 32;
  258.         box.bottom = box.top + 32;
  259.         
  260.         cicon = GetCIcon(iconID);
  261.         if (cicon)
  262.         {
  263.             PlotCIcon(&box,cicon);
  264.             DisposeCIcon(cicon);
  265.         }
  266.         else
  267.         {
  268.             Handle    icon;
  269.             
  270.             icon = GetIcon(iconID);
  271.             if (icon)
  272.             {
  273.                 PlotIcon(&box,icon);
  274.                 ReleaseResource(icon);
  275.             }
  276.         }
  277.     }
  278.     
  279.     offset = DrawAutoSizedText(info->errorText,systemFont,12,kCSATextBoxLeft,kCSATextBoxTop,kCSATextBoxWidth,true);
  280.     DrawAutoSizedText(info->detailText,applFont,10,kCSATextBoxLeft,offset + kCSATextBoxSeparator,kCSATextBoxWidth,true);
  281. }
  282.  
  283.  
  284.  
  285.  
  286.  
  287. short DrawAutoSizedText(StringPtr text,short font,short size,short left,short top,short width,Boolean draw)
  288. {
  289.     QDContext    context;
  290.     FontInfo    fInfo;
  291.     Str255        ctext;
  292.     UInt32        index,len,start,end;
  293.     short        cur;
  294.     
  295.     
  296.     if (!text || !(*text))
  297.         return top;
  298.     
  299.     TextFont(font);
  300.     TextSize(size);
  301.     GetFontInfo(&fInfo);
  302.     
  303.     pstrcpy(ctext,text);
  304.     len = 1 + ctext[0];
  305.     start = end = 1;
  306.     
  307.     for (index = 1;index < len;index++)
  308.     {
  309.         if (isspace(ctext[index]))
  310.         {
  311.             cur = TextWidth(ctext,start,index - start);
  312.             if (cur > width)
  313.             {
  314.                 if (draw)
  315.                 {
  316.                     MoveTo(left,top + fInfo.ascent);
  317.                     DrawText(ctext,start,end - start);
  318.                 }
  319.                 
  320.                 start = end + 1;
  321.                 top += fInfo.ascent + fInfo.descent + fInfo.leading;
  322.             }
  323.             
  324.             end = index;
  325.         }
  326.     }
  327.     
  328.     if (draw)
  329.     {
  330.         MoveTo(left,top + fInfo.ascent);
  331.         DrawText(ctext,start,index - start);
  332.     }
  333.     
  334.     top += fInfo.ascent + fInfo.descent;
  335.     return top;
  336. }
  337.  
  338.  
  339.  
  340.  
  341.  
  342. Boolean WeAreFrontProcess(void)
  343. {
  344.     ProcessSerialNumber        myPSN,frontPSN;
  345.     Boolean                    same;
  346.     
  347.     
  348.     GetCurrentProcess(&myPSN);
  349.     GetFrontProcess(&frontPSN);
  350.     SameProcess(&myPSN,&frontPSN,&same);
  351.     return same;
  352. }
  353.